home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / gcc263-src.lha / gcc-2.6.3 / config / gmicro / gmicro.c next >
C/C++ Source or Header  |  1992-07-27  |  21KB  |  984 lines

  1. /* Subroutines for insn-output.c for the Gmicro.
  2.    Ported by Masanobu Yuhara, Fujitsu Laboratories LTD.
  3.    (yuhara@flab.fujitsu.co.jp)
  4.  
  5.    Copyright (C) 1990, 1991 Free Software Foundation, Inc.
  6.  
  7. This file is part of GNU CC.
  8.  
  9. GNU CC is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2, or (at your option)
  12. any later version.
  13.  
  14. GNU CC is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. Among other things, the copyright
  20. notice and this notice must be preserved on all copies.
  21.  
  22. You should have received a copy of the GNU General Public License
  23. along with GNU CC; see the file COPYING.  If not, write to
  24. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  25.  
  26.  
  27. #include <stdio.h>
  28. #include "config.h"
  29. #include "rtl.h"
  30. #include "regs.h"
  31. #include "hard-reg-set.h"
  32. #include "real.h"
  33. #include "insn-config.h"
  34. #include "conditions.h"
  35. #include "insn-flags.h"
  36. #include "output.h"
  37. #include "insn-attr.h"
  38.  
  39. extern char *rtx_name[];
  40.  
  41. mypr (s, a1, a2, a3, a4, a5)
  42.      char *s;
  43.      int a1, a2, a3, a4, a5;
  44. {
  45.   fprintf (stderr, s, a1, a2, a3, a4, a5);
  46. }
  47.  
  48. myprcode (i)
  49.      int i;
  50. {
  51.   if (i < 0 || i > 90)
  52.     fprintf (stderr, "code = %d\n", i);
  53.   else
  54.     fprintf (stderr, "code = %s\n", rtx_name[i]);
  55. }
  56.  
  57. myabort (i)
  58.      int i;
  59. {
  60.   fprintf (stderr, "myabort");
  61.   myprcode (i);
  62. }
  63.  
  64.  
  65. /* This is how to output an ascii string.  */
  66. /* See ASM_OUTPUT_ASCII in gmicro.h.  */
  67. output_ascii (file, p, size)
  68.      FILE *file;
  69.      char *p;
  70.      int size;
  71. {
  72.   int i;
  73.   int in_quote = 0;
  74.   register int c;
  75.  
  76.   fprintf (file, "\t.sdata ");
  77.  
  78.   for (i = 0; i < size; i++) 
  79.     {
  80.       c = p[i];
  81.       if (c >= ' ' && c < 0x7f) 
  82.     {
  83.       if (!in_quote) 
  84.         {
  85.           putc ('"', file);
  86.           in_quote = 1;
  87.         }
  88.       putc (c, file);
  89.     }
  90.       else 
  91.     {
  92.       if (in_quote) 
  93.         {
  94.           putc ('"', file);
  95.           in_quote = 0;
  96.         }
  97.       fprintf (file, "<%d>", c);
  98.     }
  99.     }
  100.   if (in_quote)
  101.     putc ('"', file);
  102.   putc ('\n', file);
  103. }
  104.  
  105.  
  106. /* call this when GET_CODE (index) is MULT. */
  107. print_scaled_index (file, index)
  108.      FILE *file;
  109.      register rtx index;
  110. {
  111.   register rtx ireg;
  112.   int scale;
  113.  
  114.   if (GET_CODE (XEXP (index, 0)) == REG) 
  115.     {
  116.       ireg = XEXP (index, 0);
  117.       scale = INTVAL (XEXP (index, 1));
  118.     }
  119.   else 
  120.     {
  121.       ireg = XEXP (index, 1);
  122.       scale = INTVAL (XEXP (index, 0));
  123.     }
  124.   if (scale == 1)
  125.     fprintf (file, "%s", reg_names[REGNO (ireg)]);
  126.   else
  127.     fprintf (file, "%s*%d", reg_names[REGNO (ireg)], scale);
  128. }
  129.     
  130.  
  131. print_operand_address (file, addr)
  132.      FILE *file;
  133.      register rtx addr;
  134. {
  135.   register rtx xtmp0, xtmp1, breg, ixreg;
  136.   int scale;
  137.   int needcomma = 0;
  138.   rtx offset;
  139.  
  140.   fprintf (file, "@");
  141.  retry:
  142.   switch (GET_CODE (addr)) 
  143.     {
  144.     case MEM:
  145.       fprintf (file, "@");
  146.       addr = XEXP (addr, 0);
  147.       goto retry;
  148.  
  149.     case REG:
  150.       fprintf (file, "%s", reg_names[REGNO (addr)]);
  151.       break;
  152.  
  153.     case MULT:
  154.       print_scaled_index (file, addr);
  155.       break;
  156.  
  157.     case PRE_DEC:
  158.       fprintf (file, "-%s", reg_names[REGNO (XEXP (addr, 0))]);
  159.       break;
  160.  
  161.     case POST_INC:
  162.       fprintf (file, "%s+", reg_names[REGNO (XEXP (addr, 0))]);
  163.       break;
  164.  
  165.     case PLUS:
  166.       xtmp0 = XEXP (addr, 0);
  167.       xtmp1 = XEXP (addr, 1);
  168.       ixreg = 0;    breg = 0;
  169.       offset = 0;
  170.       if (CONSTANT_ADDRESS_P (xtmp0)) 
  171.     {
  172.       offset = xtmp0;
  173.       breg = xtmp1;
  174.     }
  175.       else if (CONSTANT_ADDRESS_P (xtmp1)) 
  176.     {
  177.       offset = xtmp1;
  178.       breg = xtmp0;
  179.     }
  180.       else 
  181.     {
  182.       goto NOT_DISP;
  183.     }
  184.  
  185.       if (REG_CODE_BASE_P (breg))
  186.     goto PRINT_MEM;
  187.  
  188.       if (GET_CODE (breg) == MULT) 
  189.     {
  190.       if (REG_CODE_INDEX_P (XEXP (breg, 0))) 
  191.         {
  192.           ixreg = XEXP (breg, 0);
  193.           scale = INTVAL (XEXP (breg, 1));
  194.           breg = 0;
  195.         }
  196.       else 
  197.         {
  198.           ixreg = XEXP (breg, 1);
  199.           scale = INTVAL (XEXP (breg, 0));
  200.           breg = 0;
  201.         }
  202.       goto PRINT_MEM;
  203.     }
  204.  
  205.       /* GET_CODE (breg) must be PLUS here. */
  206.       xtmp0 = XEXP (breg, 0);
  207.       xtmp1 = XEXP (breg, 1);
  208.       if (REG_CODE_BASE_P (xtmp0)) 
  209.     {
  210.       breg = xtmp0;
  211.       xtmp0 = xtmp1;
  212.     }
  213.       else 
  214.     {
  215.       breg = xtmp1;
  216.       /* xtmp0 = xtmp0; */
  217.     }
  218.  
  219.       if (GET_CODE (xtmp0) == MULT) 
  220.     {
  221.       if (REG_CODE_INDEX_P (XEXP (xtmp0, 0))) 
  222.         {
  223.           ixreg = XEXP (xtmp0, 0);
  224.           scale = INTVAL (XEXP (xtmp0, 1));
  225.         }
  226.       else 
  227.         {
  228.           ixreg = XEXP (xtmp0, 1);
  229.           scale = INTVAL (XEXP (xtmp0, 0));
  230.         }
  231.     }
  232.       else 
  233.     {
  234.       ixreg = xtmp0;
  235.       scale = 1;
  236.     }
  237.       goto PRINT_MEM;
  238.  
  239.     NOT_DISP:
  240.       if (REG_CODE_BASE_P (xtmp0)) 
  241.     {
  242.       breg = xtmp0;
  243.       xtmp0 = xtmp1;
  244.     }
  245.       else if (REG_CODE_BASE_P (xtmp1)) 
  246.     {
  247.       breg = xtmp1;
  248.       /* xtmp0 = xtmp0; */
  249.     }
  250.       else
  251.     goto NOT_BASE;
  252.     
  253.       if (REG_CODE_INDEX_P (xtmp0)) 
  254.     {
  255.       ixreg = xtmp0;
  256.       scale = 1;
  257.       goto PRINT_MEM;
  258.     }
  259.       else if (CONSTANT_ADDRESS_P (xtmp0)) 
  260.     {
  261.       offset = xtmp0;
  262.       goto PRINT_MEM;
  263.     }
  264.       else if (GET_CODE (xtmp0) == MULT) 
  265.     {
  266.       if (REG_CODE_INDEX_P (XEXP (xtmp0, 0))) 
  267.         {
  268.           ixreg = XEXP (xtmp0, 0);
  269.           scale = INTVAL (XEXP (xtmp0, 1));
  270.         }
  271.       else 
  272.         {
  273.           ixreg = XEXP (xtmp0, 1);
  274.           scale = INTVAL (XEXP (xtmp0, 0));
  275.         }
  276.       goto PRINT_MEM;
  277.     }
  278.  
  279.       /* GET_CODE (xtmp0) must be PLUS. */
  280.       xtmp1 = XEXP (xtmp0, 1);
  281.       xtmp0 = XEXP (xtmp0, 0);
  282.  
  283.       if (CONSTANT_ADDRESS_P (xtmp0)) 
  284.     {
  285.       offset = xtmp0;
  286.       xtmp0 = xtmp1;
  287.     }
  288.       else 
  289.     {
  290.       offset = xtmp1;
  291.       /* xtmp0 = xtmp0; */
  292.     }
  293.  
  294.       if (REG_CODE_INDEX_P (xtmp0)) 
  295.     {
  296.       ixreg = xtmp0;
  297.     }
  298.       else 
  299.     {            /* GET_CODE (xtmp0) must be MULT. */
  300.       if (REG_CODE_INDEX_P (XEXP (xtmp0, 0))) 
  301.         {
  302.           ixreg = XEXP (xtmp0, 0);
  303.           scale = INTVAL (XEXP (xtmp0, 1));
  304.         }
  305.       else 
  306.         {
  307.           ixreg = XEXP (xtmp0, 1);
  308.           scale = INTVAL (XEXP (xtmp0, 0));
  309.         }
  310.     }
  311.       goto PRINT_MEM;
  312.  
  313.     NOT_BASE:
  314.       if (GET_CODE (xtmp0) == PLUS) 
  315.     {
  316.       ixreg = xtmp1;
  317.       /* xtmp0 = xtmp0; */
  318.     }
  319.       else 
  320.     {
  321.       ixreg = xtmp0;
  322.       xtmp0 = xtmp1;
  323.     }
  324.  
  325.       if (REG_CODE_INDEX_P (ixreg)) 
  326.     {
  327.       scale = 1;
  328.     }
  329.       else if (REG_CODE_INDEX_P (XEXP (ixreg, 0))) 
  330.     {
  331.       scale = INTVAL (XEXP (ixreg, 1));
  332.       ixreg = XEXP (ixreg, 0);
  333.     }
  334.       else 
  335.     {            /* was else if with no condition. OK ??? */
  336.       scale = INTVAL (XEXP (ixreg, 0));
  337.       ixreg = XEXP (ixreg, 1);
  338.     }
  339.  
  340.       if (REG_CODE_BASE_P (XEXP (xtmp0, 0))) 
  341.     {
  342.       breg = XEXP (xtmp0, 0);
  343.       offset = XEXP (xtmp0, 1);
  344.     }
  345.       else 
  346.     {
  347.       breg = XEXP (xtmp0, 1);
  348.       offset = XEXP (xtmp0, 0);
  349.     }
  350.  
  351.     PRINT_MEM:
  352.       if (breg == 0 && ixreg == 0) 
  353.     {
  354.       output_address (offset);
  355.       break;
  356.     }
  357.       else if (ixreg == 0 && offset == 0) 
  358.     {
  359.       fprintf (file, "%s", reg_names[REGNO (breg)]);
  360.       break;
  361.     }
  362.       else 
  363.     {
  364.       fprintf (file, "(");
  365.       if (offset != 0) 
  366.         {
  367.           output_addr_const (file, offset);
  368.           needcomma = 1;
  369.         }
  370.       if (breg != 0) 
  371.         {
  372.           if (needcomma)
  373.         fprintf (file, ",");
  374.           fprintf (file, "%s", reg_names[REGNO (breg)]);
  375.           needcomma = 1;
  376.         }
  377.       if (ixreg != 0) 
  378.         {
  379.           if (needcomma)
  380.         fprintf (file, ",");
  381.           fprintf (file, "%s", reg_names[REGNO (ixreg)]);
  382.           if (scale != 1)
  383.         fprintf (file,"*%d", scale);
  384.         }
  385.       fprintf (file, ")");
  386.  
  387.       break;
  388.     }
  389.  
  390.     default:
  391.       output_addr_const (file, addr);
  392.     }
  393. }
  394.  
  395.  
  396.  
  397. /* Return a REG that occurs in ADDR with coefficient 1.
  398.    ADDR can be effectively incremented by incrementing REG.  */
  399.  
  400. static rtx
  401. find_addr_reg (addr)
  402.      rtx addr;
  403. {
  404.   while (GET_CODE (addr) == PLUS)
  405.     {
  406.       if (GET_CODE (XEXP (addr, 0)) == REG)
  407.     addr = XEXP (addr, 0);
  408.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  409.     addr = XEXP (addr, 1);
  410.       else if (GET_CODE (XEXP (addr, 0)) == PLUS)
  411.     addr = XEXP (addr, 0);
  412.       else if (GET_CODE (XEXP (addr, 1)) == PLUS)
  413.     addr = XEXP (addr, 1);
  414.     }
  415.   if (GET_CODE (addr) == REG)
  416.     return addr;
  417.   return 0;
  418. }
  419.  
  420.  
  421.     /* Return the best assembler insn template
  422.     for moving operands[1] into operands[0] as a fullword.  */
  423.  
  424. static char *
  425. singlemove_string (operands)
  426.      rtx *operands;
  427. {
  428.   if (FPU_REG_P (operands[0]) || FPU_REG_P (operands[1])) 
  429.     {
  430.       if (GREG_P (operands[0]) || GREG_P (operands[1])) 
  431.     {
  432.       myabort (101);    /* Not Supported yet !! */
  433.     }
  434.       else 
  435.     {
  436.       return "fmov.s %1,%0";
  437.     }
  438.     }
  439.   return "mov.w %1,%0";
  440. }
  441.  
  442.  
  443. /* Output assembler code to perform a doubleword move insn
  444.    with operands OPERANDS.  */
  445.  
  446. char *
  447. output_move_double (operands)
  448.      rtx *operands;
  449. {
  450.   enum 
  451.     { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP }
  452.   optype0, optype1;
  453.   rtx latehalf[2];
  454.   rtx addreg0 = 0, addreg1 = 0;
  455.  
  456.   /* First classify both operands.  */
  457.  
  458.   if (REG_P (operands[0]))
  459.     optype0 = REGOP;
  460.   else if (offsettable_memref_p (operands[0]))
  461.     optype0 = OFFSOP;
  462.   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
  463.     optype0 = POPOP;
  464.   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
  465.     optype0 = PUSHOP;
  466.   else if (GET_CODE (operands[0]) == MEM)
  467.     optype0 = MEMOP;
  468.   else
  469.     optype0 = RNDOP;
  470.  
  471.   if (REG_P (operands[1]))
  472.     optype1 = REGOP;
  473.   else if (CONSTANT_P (operands[1]))
  474.     optype1 = CNSTOP;
  475.   else if (offsettable_memref_p (operands[1]))
  476.     optype1 = OFFSOP;
  477.   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  478.     optype1 = POPOP;
  479.   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
  480.     optype1 = PUSHOP;
  481.   else if (GET_CODE (operands[1]) == MEM)
  482.     optype1 = MEMOP;
  483.   else
  484.     optype1 = RNDOP;
  485.  
  486.   /* Check for the cases that the operand constraints are not
  487.      supposed to allow to happen.  Abort if we get one,
  488.      because generating code for these cases is painful.  */
  489.  
  490.   if (optype0 == RNDOP || optype1 == RNDOP)
  491.     myabort (102);
  492.  
  493.   /* If one operand is decrementing and one is incrementing
  494.      decrement the former register explicitly
  495.      and change that operand into ordinary indexing.  */
  496.  
  497.   if (optype0 == PUSHOP && optype1 == POPOP)
  498.     {
  499.       operands[0] = XEXP (XEXP (operands[0], 0), 0);
  500.       output_asm_insn ("sub.w %#8,%0", operands);
  501.       operands[0] = gen_rtx (MEM, DImode, operands[0]);
  502.       optype0 = OFFSOP;
  503.     }
  504.   if (optype0 == POPOP && optype1 == PUSHOP)
  505.     {
  506.       operands[1] = XEXP (XEXP (operands[1], 0), 0);
  507.       output_asm_insn ("sub.w %#8,%1", operands);
  508.       operands[1] = gen_rtx (MEM, DImode, operands[1]);
  509.       optype1 = OFFSOP;
  510.     }
  511.  
  512.   /* If an operand is an unoffsettable memory ref, find a register
  513.      we can increment temporarily to make it refer to the second word.  */
  514.  
  515.   if (optype0 == MEMOP)
  516.     addreg0 = find_addr_reg (operands[0]);
  517.  
  518.   if (optype1 == MEMOP)
  519.     addreg1 = find_addr_reg (operands[1]);
  520.  
  521.   /* Ok, we can do one word at a time.
  522.      Normally we do the low-numbered word first,
  523.      but if either operand is autodecrementing then we
  524.      do the high-numbered word first.
  525.      
  526.      In either case, set up in LATEHALF the operands to use
  527.      for the high-numbered word and in some cases alter the
  528.      operands in OPERANDS to be suitable for the low-numbered word.  */
  529.  
  530.   if (optype0 == REGOP)
  531.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  532.   else if (optype0 == OFFSOP)
  533.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  534.   else
  535.     latehalf[0] = operands[0];
  536.  
  537.   if (optype1 == REGOP)
  538.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  539.   else if (optype1 == OFFSOP)
  540.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  541.   else if (optype1 == CNSTOP)
  542.     {
  543.       if (GET_CODE (operands[1]) == CONST_DOUBLE)
  544.     split_double (operands[1], &operands[1], &latehalf[1]);
  545.       else if (CONSTANT_P (operands[1]))
  546.     latehalf[1] = const0_rtx;
  547.     }
  548.   else
  549.     latehalf[1] = operands[1];
  550.  
  551.   /* If insn is effectively movd N(sp),-(sp) then we will do the
  552.      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
  553.      for the low word as well, to compensate for the first decrement of sp.  */
  554.   if (optype0 == PUSHOP
  555.       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
  556.       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
  557.     operands[1] = latehalf[1];
  558.  
  559.   /* If one or both operands autodecrementing,
  560.      do the two words, high-numbered first.  */
  561.  
  562.   /* Likewise,  the first move would clobber the source of the second one,
  563.      do them in the other order.  This happens only for registers;
  564.      such overlap can't happen in memory unless the user explicitly
  565.      sets it up, and that is an undefined circumstance.  */
  566.  
  567.   if (optype0 == PUSHOP || optype1 == PUSHOP
  568.       || (optype0 == REGOP && optype1 == REGOP
  569.       && REGNO (operands[0]) == REGNO (latehalf[1])))
  570.     {
  571.       /* Make any unoffsettable addresses point at high-numbered word.  */
  572.       if (addreg0)
  573.     output_asm_insn ("add.w %#4,%0", &addreg0);
  574.       if (addreg1)
  575.     output_asm_insn ("add.w %#4,%0", &addreg1);
  576.  
  577.       /* Do that word.  */
  578.       output_asm_insn (singlemove_string (latehalf), latehalf);
  579.  
  580.       /* Undo the adds we just did.  */
  581.       if (addreg0)
  582.     output_asm_insn ("sub.w %#4,%0", &addreg0);
  583.       if (addreg1)
  584.     output_asm_insn ("sub.w %#4,%0", &addreg1);
  585.  
  586.       /* Do low-numbered word.  */
  587.       return singlemove_string (operands);
  588.     }
  589.  
  590.   /* Normal case: do the two words, low-numbered first.  */
  591.  
  592.   output_asm_insn (singlemove_string (operands), operands);
  593.  
  594.   /* Make any unoffsettable addresses point at high-numbered word.  */
  595.   if (addreg0)
  596.     output_asm_insn ("add.w %#4,%0", &addreg0);
  597.   if (addreg1)
  598.     output_asm_insn ("add.w %#4,%0", &addreg1);
  599.  
  600.   /* Do that word.  */
  601.   output_asm_insn (singlemove_string (latehalf), latehalf);
  602.  
  603.   /* Undo the adds we just did.  */
  604.   if (addreg0)
  605.     output_asm_insn ("sub.w %#4,%0", &addreg0);
  606.   if (addreg1)
  607.     output_asm_insn ("sub.w %#4,%0", &addreg1);
  608.  
  609.   return "";
  610. }
  611.  
  612. /* Move const_double to floating point register (DF) */
  613. char *
  614. output_move_const_double (operands)
  615.      rtx *operands;
  616. {
  617.   int code = standard_fpu_constant_p (operands[1]);
  618.  
  619.   if (FPU_REG_P (operands[0])) 
  620.     {
  621.       if (code != 0)
  622.     {
  623.       static char buf[40];
  624.  
  625.       sprintf (buf, "fmvr from%d,%%0.d", code);
  626.       return buf;
  627.     }
  628.       else 
  629.     {
  630.       return "fmov %1,%0.d";
  631.     }
  632.     }
  633.   else if (GREG_P (operands[0])) 
  634.     {
  635.       rtx xoperands[2];
  636.       xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  637.       xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
  638.                   CONST_DOUBLE_HIGH (operands[1]));
  639.       output_asm_insn ("mov.w %1,%0", xoperands);
  640.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  641.                  CONST_DOUBLE_LOW (operands[1]));
  642.       return "mov.w %1,%0";
  643.     }
  644.   else 
  645.     {
  646.       return output_move_double (operands); /* ?????? */
  647.     }
  648. }
  649.  
  650. char *
  651. output_move_const_single (operands)
  652.      rtx *operands;
  653. {
  654.   int code = standard_fpu_constant_p (operands[1]);
  655.   static char buf[40];
  656.  
  657.   if (FPU_REG_P (operands[0])) 
  658.     {
  659.       if (code != 0)
  660.     {
  661.       sprintf (buf, "fmvr from%d,%%0.s", code);
  662.       return buf;
  663.     }
  664.       return "fmov.s %f1,%0";
  665.     }
  666.   else 
  667.     return "mov.w %f1,%0";
  668. }
  669.  
  670.  
  671. /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
  672.    from the "fmvr" instruction of the Gmicro FPU.
  673.    The value, anded with 0xff, gives the code to use in fmovecr
  674.    to get the desired constant.  */
  675.  
  676.   u.i[0] = CONST_DOUBLE_LOW (x);
  677.   u.i[1] = CONST_DOUBLE_HIGH (x);
  678.   d = u.d;
  679.  
  680.   if (d == 0.0)            /* +0.0 */
  681.     return 0x0;
  682.   /* Note: there are various other constants available
  683.      but it is a nuisance to put in their values here.  */
  684.   if (d == 1.0)            /* +1.0 */
  685.     return 0x1;
  686.  
  687.   /*
  688.    * Stuff that looks different if it's single or double
  689.    */
  690.   if (GET_MODE (x) == SFmode)
  691.     {
  692.       if (d == S_PI)
  693.     return 0x2;
  694.       if (d == (S_PI / 2.0))
  695.     return 0x3;
  696.       if (d == S_E)
  697.     return 0x4;
  698.       if (d == S_LOGEof2)
  699.     return 0x5;
  700.       if (d == S_LOGEof10)
  701.     return 0x6;
  702.       if (d == S_LOG10of2)
  703.     return 0x7;
  704.       if (d == S_LOG10ofE)
  705.     return 0x8;
  706.       if (d == S_LOG2ofE)
  707.     return 0x9;
  708.     }
  709.   else
  710.     {
  711.       if (d == D_PI)
  712.     return 0x2;
  713.       if (d == (D_PI / 2.0))
  714.     return 0x3;
  715.       if (d == D_E)
  716.     return 0x4;
  717.       if (d == D_LOGEof2)
  718.     return 0x5;
  719.       if (d == D_LOGEof10)
  720.     return 0x6;
  721.       if (d == D_LOG10of2)
  722.     return 0x7;
  723.       if (d == D_LOG10ofE)
  724.     return 0x8;
  725.       if (d == D_LOG2ofE)
  726.     return 0x9;
  727.     }
  728.  
  729.   return 0;
  730. }
  731.  
  732. #undef S_PI
  733. #undef D_PI
  734. #undef S_E
  735. #undef D_E
  736. #undef S_LOGEof2
  737. #undef D_LOGEof2
  738. #undef S_LOGEof10
  739. #undef D_LOGEof10
  740. #undef S_LOG10of2
  741. #undef D_LOG10of2
  742. #undef S_LOG10ofE
  743. #undef D_LOG10ofE
  744. #undef S_LOG2ofE
  745. #undef D_LOG2ofE
  746.  
  747. /* dest should be operand 0 */
  748. /* imm should be operand 1 */
  749.  
  750. extern char *sub_imm_word ();
  751.  
  752. char *
  753. add_imm_word (imm, dest, immp)
  754.      int imm;
  755.      rtx dest, *immp;
  756. {
  757.   int is_reg, short_ok;
  758.  
  759.  
  760.   if (imm < 0) 
  761.     {
  762.       *immp = gen_rtx (CONST_INT, VOIDmode, -imm);
  763.       return sub_imm_word (-imm, dest);
  764.     }
  765.     
  766.   if (imm == 0)
  767.     return "mov:l.w #0,%0";
  768.     
  769.   short_ok = short_format_ok (dest);
  770.  
  771.   if (short_ok && imm <= 8)
  772.     return "add:q %1,%0.w";
  773.  
  774.   if (imm < 128)
  775.     return "add:e %1,%0.w";
  776.  
  777.   is_reg = (GET_CODE (dest) == REG);
  778.  
  779.   if (is_reg)
  780.     return "add:l %1,%0.w";
  781.     
  782.   if (short_ok)
  783.     return "add:i %1,%0.w";
  784.     
  785.   return "add %1,%0.w";
  786. }
  787.  
  788. char *
  789. sub_imm_word (imm, dest, immp)
  790.      int imm;
  791.      rtx dest, *immp;
  792. {
  793.   int is_reg, short_ok;
  794.  
  795.   if (imm < 0 &&  imm != 0x80000000) 
  796.     {
  797.       *immp = gen_rtx (CONST_INT, VOIDmode, -imm);
  798.       return add_imm_word (-imm, dest);
  799.     }
  800.     
  801.   if (imm == 0)
  802.     return "mov:z.w #0,%0";
  803.     
  804.   short_ok = short_format_ok (dest);
  805.  
  806.   if (short_ok && imm <= 8)
  807.     return "sub:q %1,%0.w";
  808.  
  809.   if (imm < 128)
  810.     return "sub:e %1,%0.w";
  811.  
  812.   is_reg = (GET_CODE (dest) == REG);
  813.  
  814.   if (is_reg)
  815.     return "sub:l %1,%0.w";
  816.     
  817.   if (short_ok)
  818.     return "sub:i %1,%0.w";
  819.     
  820.   return "sub %1,%0.w";
  821. }
  822.  
  823. int
  824. short_format_ok (x)
  825.      rtx x;
  826. {
  827.   rtx x0, x1;
  828.  
  829.   if (GET_CODE (x) == REG)
  830.     return 1;
  831.  
  832.   if (GET_CODE (x) == MEM 
  833.       && GET_CODE (XEXP (x, 0)) == PLUS) 
  834.     {
  835.       x0 = XEXP (XEXP (x, 0), 0);
  836.       x1 = XEXP (XEXP (x, 0), 1);
  837.       return ((GET_CODE (x0) == REG
  838.            && CONSTANT_P (x1)
  839.            && ((unsigned) (INTVAL (x1) + 0x8000)  < 0x10000))
  840.           ||
  841.           (GET_CODE (x1) == REG
  842.            && CONSTANT_P (x0)
  843.            && ((unsigned) (INTVAL (x0) + 0x8000)  < 0x10000)));
  844.     }
  845.  
  846.   return 0;
  847. }
  848.  
  849. myoutput_sp_adjust (file, op, fsize)
  850.      FILE *file;
  851.      char *op;
  852.      int fsize;
  853. {
  854.   if (fsize == 0)
  855.     ;
  856.   else if (fsize < 8)
  857.     fprintf (file, "\t%s:q #%d,sp.w\n", op, fsize);
  858.   else if (fsize < 128)
  859.     fprintf (file, "\t%s:e #%d,sp.w\n", op, fsize);
  860.   else
  861.     fprintf (file, "\t%s:l #%d,sp.w\n", op, fsize);
  862. }
  863.  
  864.  
  865. char *
  866. mov_imm_word (imm, dest)
  867.      int imm;
  868.      rtx dest;
  869. {
  870.   int is_reg, short_ok;
  871.  
  872.   if (imm == 0)
  873.     return "mov:z.w #0,%0";
  874.     
  875.   short_ok = short_format_ok (dest);
  876.  
  877.   if (short_ok && imm > 0 && imm <= 8)
  878.     return "mov:q %1,%0.w";
  879.  
  880.   if (-128 <= imm && imm < 128)
  881.     return "mov:e %1,%0.w";
  882.  
  883.   is_reg = (GET_CODE (dest) == REG);
  884.  
  885.   if (is_reg)
  886.     return "mov:l %1,%0.w";
  887.     
  888.   if (short_ok)
  889.     return "mov:i %1,%0.w";
  890.     
  891.   return "mov %1,%0.w";
  892. }
  893.  
  894. char *
  895. cmp_imm_word (imm, dest)
  896.      int imm;
  897.      rtx dest;
  898. {
  899.   int is_reg, short_ok;
  900.  
  901.   if (imm == 0)
  902.     return "cmp:z.w #0,%0";
  903.     
  904.   short_ok = short_format_ok (dest);
  905.  
  906.   if (short_ok && imm >0 && imm <= 8)
  907.     return "cmp:q %1,%0.w";
  908.  
  909.   if (-128 <= imm && imm < 128)
  910.     return "cmp:e %1,%0.w";
  911.  
  912.   is_reg = (GET_CODE (dest) == REG);
  913.  
  914.   if (is_reg)
  915.     return "cmp:l %1,%0.w";
  916.     
  917.   if (short_ok)
  918.     return "cmp:i %1,%0.w";
  919.     
  920.   return "cmp %1,%0.w";
  921. }
  922.  
  923. char *
  924. push_imm_word (imm)
  925.      int imm;
  926. {
  927.   if (imm == 0)
  928.     return "mov:z.w #0,%-";
  929.     
  930.   if (imm > 0 && imm <= 8)
  931.     return "mov:q %1,%-.w";
  932.  
  933.   if (-128 <= imm && imm < 128)
  934.     return "mov:e %1,%-.w";
  935.  
  936.   return "mov:g %1,%-.w";
  937.     
  938.   /* In some cases, g-format may be better than I format.??
  939.      return "mov %1,%0.w";
  940.      */
  941. }
  942.  
  943. my_signed_comp (insn)
  944.      rtx insn;
  945. {
  946.   rtx my_insn;
  947.  
  948.   my_insn = NEXT_INSN (insn);
  949.   if (GET_CODE (my_insn) != JUMP_INSN) 
  950.     {
  951.       fprintf (stderr, "my_signed_comp: Not Jump_insn ");
  952.       myabort (GET_CODE (my_insn));
  953.     }
  954.   my_insn = PATTERN (my_insn);
  955.   if (GET_CODE (my_insn) != SET) 
  956.     {
  957.       fprintf (stderr, "my_signed_comp: Not Set ");
  958.       myabort (GET_CODE (my_insn));
  959.     }
  960.   my_insn = SET_SRC (my_insn);
  961.   if (GET_CODE (my_insn) != IF_THEN_ELSE) 
  962.     {
  963.       fprintf (stderr, "my_signed_comp: Not if_then_else ");
  964.       myabort (GET_CODE (my_insn));
  965.     }
  966.   switch (GET_CODE (XEXP (my_insn, 0)))
  967.     {
  968.     case NE:
  969.     case EQ:
  970.     case GE:
  971.     case GT:
  972.     case LE:
  973.     case LT:
  974.       return 1;
  975.     case GEU:
  976.     case GTU:
  977.     case LEU:
  978.     case LTU:
  979.       return 0;
  980.     }
  981.   fprintf (stderr, "my_signed_comp: Not cccc ");
  982.   myabort (GET_CODE (XEXP (my_insn, 0)));
  983. }
  984.